package chapter9;

import java.util.Collection;
import java.util.List;

/**
 * 关于泛型方法和通配符的一些区别和使用场景
 */
public class GenericDesc {

}

/**
 * 模拟JDK中Collection类的两个方法，使用泛型通配符
 */
interface MyCollection<E> {
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
}

/**
 * 和上边的两个方法功能一样，只不过下边的方法使用泛型方法来实现
 * 下边两个方法中泛型参数T只使用了一次，T的唯一效果是可以在不同的调用点
 * 传入不同的实际类型，对于这样的情况应该使用通配符
 *
 * 泛型方法允许泛型参数被用来表示方法的一个或多个参数之间的类型依赖关系，或者方法
 * 返回值和参数之间的类型依赖关系，如果没有这样的关系就不该使用泛型方法
 * @param <E>
 */
interface CollectionWithGenericMethod<E> {
    <T> boolean containsAll(Collection<T> c);
    <T extends E> boolean addAll(Collection<T> c);
}

/**
 * 下边的方法同时使用类型通配符和泛型方法，dest和src之间存在明显的依赖关系
 * src中复制出来的元素必须能够放入dest中，所以源src的集合元素类型必须是src本身
 * 或者它的子类。
 * JDK中也提供了相同功能的方法，但是JDK中的方法使用通配符实现，并没有实现泛型方法
 * 因为在这个功能下无需向src集合中添加元素也无需修改src中的元素。所以可以采用通配符
 */
class MyCollection2 {
    public static <T> void copy(List<T> dest, List<? extends T> src) {

    }

    //不使用类型通配符，将上列方法改为泛型方法
    public static <T, S extends T> void copy1(List<T> dest, List<S> src) {

    }
}



